#include <iostream>
#include <string>
#include <vector>
#include <cassert>
#include <mutex>
#include <semaphore.h>

// 信号量

template <class T>
class ringQueue
{
private:
    std::vector<T> _queue;
    int _capacity;
    sem_t _spaceSem;
    sem_t _dataSem;
    int _productorStep;
    int _consumerStep;
    std::mutex _pmutex;
    std::mutex _cmutex;

private:
    void P(sem_t &sem)
    {
        int n = sem_wait(&sem);
        assert(n == 0);
        void(n);
    }

    void V(sem_t &sem)
    {
        int n = sem_post(&sem);
        assert(n == 0);
        void(n);
    }

public:
    ringQueue(int capacity)
        : _capacity(capacity), _queue(_capacity)
    {
        int n = sem_init(&_spaceSem, 0, _capacity);
        assert(n == 0);
        n = sem_init(&_dataSem, 0, 0);
        assert(n == 0);
        _productorStep = _consumerStep = 0;
    }

    void push(const T &data)
    {
        P(_spaceSem);
        std::unique_lock<std::mutex> lock(_pmutex);
        _queue[_productorStep++] = data;
        _productorStep %= _capacity;
        V(_dataSem);
    }

    void pop(T *data)
    {
        P(_dataSem);
        std::unique_lock<std::mutex> lock(_pmutex);
        *data = _queue[_consumerStep++];
        _consumerStep %= _capacity;
        V(_spaceSem);
    }

    ~ringQueue()
    {
        sem_destroy(&_spaceSem);
        sem_destroy(&_dataSem);
    }
};